package com.bxj.mybatis.generator.plugin;

import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class ServicePlugin extends PluginAdapter {


    private String serviceProject;
    private String servicePackage;
    private String serviceImplPackage;
    private String mapperPackage;
    private String modelPackage;

    public boolean validate(List<String> warnings) {
        serviceProject = properties.getProperty("serviceProject");
        if (StringUtils.isEmpty(serviceProject))
            return false;
        servicePackage = properties.getProperty("servicePackage");
        if (StringUtils.isEmpty(servicePackage))
            return false;
        serviceImplPackage = properties.getProperty("serviceImplPackage");
        if (StringUtils.isEmpty(serviceImplPackage)) {
            return false;
        }
        mapperPackage = properties.getProperty("mapperPackage");
        if (StringUtils.isEmpty(mapperPackage)) {
            return false;
        }
        modelPackage = properties.getProperty("modelPackage");
        if (StringUtils.isEmpty(modelPackage)) {
            return false;
        }
        return true;


    }


    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {

        List<GeneratedJavaFile> answer = new ArrayList<GeneratedJavaFile>();
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);
        String serviceName = servicePackage + "." + shortName + "Service";
        if (!MybatisUtils.checkReplaceIfExists(introspectedTable, serviceProject, servicePackage, shortName + "Service.java"))
            return answer;
        Interface serviceInterface = new Interface(serviceName);
        serviceInterface.setVisibility(JavaVisibility.PUBLIC);
        MybatisUtils.addJavaDocLines(serviceInterface);
        serviceInterface.setVisibility(JavaVisibility.PUBLIC);


        CommentGenerator commentGenerator = context.getCommentGenerator();
        String serviceImplName = serviceImplPackage + "." + shortName + "ServiceImpl";
        FullyQualifiedJavaType type = new FullyQualifiedJavaType(
                serviceImplName);
        TopLevelClass topLevelClass = new TopLevelClass(type);
        MybatisUtils.addJavaDocLines(topLevelClass);
        topLevelClass.addAnnotation("@Component(\"" + paramName + "Service\")");
        topLevelClass.setVisibility(JavaVisibility.PUBLIC);
        topLevelClass.addSuperInterface(serviceInterface.getType());
        topLevelClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + shortName));
        topLevelClass.addImportedType(new FullyQualifiedJavaType(servicePackage + "." + shortName + "Service"));
        topLevelClass.addImportedType(new FullyQualifiedJavaType("org.springframework.stereotype.Component"));
        topLevelClass.addImportedType(new FullyQualifiedJavaType("javax.annotation.Resource"));
        topLevelClass.addImportedType(new FullyQualifiedJavaType(mapperPackage + ".master." + shortName + "MasterMapper"));
        topLevelClass.addImportedType(new FullyQualifiedJavaType(mapperPackage + ".slave." + shortName + "SlaveMapper"));

        //@Resource
        //***SlaveMapper ***slaveMapper;
        Field masterMapper = new Field(paramName + "MasterMapper", new FullyQualifiedJavaType(shortName + "MasterMapper"));
        masterMapper.addAnnotation("@Resource");
        topLevelClass.addField(masterMapper);
        //@Resource
        //***SlaveMapper ***slaveMapper;
        Field slaveMapper = new Field(paramName + "SlaveMapper", new FullyQualifiedJavaType(shortName + "SlaveMapper"));
        slaveMapper.addAnnotation("@Resource");
        topLevelClass.addField(slaveMapper);

        commentGenerator.addJavaFileComment(topLevelClass);

        addSelectSelective(answer, topLevelClass, serviceInterface, introspectedTable);
        addSelectObjectById(answer, topLevelClass, serviceInterface, introspectedTable);
        addSelectPage(answer, topLevelClass, serviceInterface, introspectedTable);
        addInsert(answer, topLevelClass, serviceInterface, introspectedTable);
        addDeleteByPrimaryKey(answer, topLevelClass, serviceInterface, introspectedTable);
        addUpdateByPrimaryKeySelective(answer, topLevelClass, serviceInterface, introspectedTable);


        return answer;
    }

    private void addSelectObjectById(List<GeneratedJavaFile> answer, TopLevelClass levelClass, Interface serviceInterface, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);
        Method method = new Method();
        method.setName(MybatisUtils.getTableProperties(introspectedTable, "selectByPrimaryKeyStatementId", "selectById"));
        if (introspectedTable.getPrimaryKeyColumns().size() > 0)
            method.addParameter(new Parameter(introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType(), "id", false));
        serviceInterface.addImportedType(new FullyQualifiedJavaType("java.util.List"));
        serviceInterface.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + shortName));
        method.setReturnType(new FullyQualifiedJavaType(shortName));
        serviceInterface.addMethod(method);

        answer.add(new GeneratedJavaFile(serviceInterface, serviceProject, context.getJavaFormatter()));

        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "selectByPrimaryKeyStatementId", "selectById"));
        if (introspectedTable.getPrimaryKeyColumns().size() > 0)
            method1.addParameter(new Parameter(introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType(), "id", false));
        levelClass.addImportedType(new FullyQualifiedJavaType("java.util.List"));
        levelClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + shortName));
        method1.setReturnType(new FullyQualifiedJavaType(shortName));
        //chatUserSlaveMapper.selectSelective(object)
        method1.addBodyLine("return " + paramName + "SlaveMapper." + MybatisUtils.getTableProperties(introspectedTable, "selectByPrimaryKeyStatementId", "selectById") + "(id);");
        levelClass.addMethod(method1);

        answer.add(new GeneratedJavaFile(levelClass, serviceProject, context.getJavaFormatter()));
    }

    //    private GeneratedJavaFile addSelectSelectiveMethod(TopLevelClass levelClass, IntrospectedTable introspectedTable) {
//        Method method = new Method();
//        method.setVisibility(JavaVisibility.PUBLIC);
//        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
//        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);
//        method.setName("selectSelective");
//        method.addParameter(new Parameter(new FullyQualifiedJavaType(shortName), paramName, false));
//        levelClass.addImportedType(new FullyQualifiedJavaType(servicePackage + "." + shortName));
//        levelClass.addImportedType(new FullyQualifiedJavaType("java.util.List"));
//        levelClass.addImportedType(new FullyQualifiedJavaType("modalPackage." + shortName));
//        method.setReturnType(new FullyQualifiedJavaType("List<" + shortName + ">"));
//        method.addBodyLine("return null;");
//        levelClass.addMethod(method);
//
//        return new GeneratedJavaFile(levelClass, serviceProject, context.getJavaFormatter());
//    }
    private void addSelectSelective(List<GeneratedJavaFile> answer, TopLevelClass levelClass, Interface serviceInterface, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);
        Method method = new Method();
        method.setName(MybatisUtils.getTableProperties(introspectedTable, "selectSelectiveStatementId", "selectSelective"));
        method.addParameter(new Parameter(new FullyQualifiedJavaType(shortName), paramName, false));
        serviceInterface.addImportedType(new FullyQualifiedJavaType("java.util.List"));
        serviceInterface.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + shortName));
        method.setReturnType(new FullyQualifiedJavaType("List<" + shortName + ">"));
        serviceInterface.addMethod(method);

        answer.add(new GeneratedJavaFile(serviceInterface, serviceProject, context.getJavaFormatter()));

        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "selectSelectiveStatementId", "selectSelective"));
        method1.addParameter(new Parameter(new FullyQualifiedJavaType(shortName), paramName, false));
        levelClass.addImportedType(new FullyQualifiedJavaType("java.util.List"));
        levelClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + shortName));
        method1.setReturnType(new FullyQualifiedJavaType("List<" + shortName + ">"));
        //chatUserSlaveMapper.selectSelective(object)
        method1.addBodyLine("return " + paramName + "SlaveMapper." + MybatisUtils.getTableProperties(introspectedTable, "selectSelectiveStatementId", "selectSelective") + "(" + paramName + ");");
        levelClass.addMethod(method1);

        answer.add(new GeneratedJavaFile(levelClass, serviceProject, context.getJavaFormatter()));

    }

    private void addSelectPage(List<GeneratedJavaFile> answer, TopLevelClass topLevelClass, Interface serviceInterface, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);
        Method method = new Method();
        method.setName(MybatisUtils.getTableProperties(introspectedTable, "selectPageStatementId", "selectPage"));
        method.addParameter(new Parameter(new FullyQualifiedJavaType(shortName), paramName, false));
        serviceInterface.addImportedType(new FullyQualifiedJavaType("com.ifeng.matrix.common.domain.PageResult"));
        method.setReturnType(new FullyQualifiedJavaType("PageResult<" + shortName + ">"));
        serviceInterface.addMethod(method);

        answer.add(new GeneratedJavaFile(serviceInterface, serviceProject, context.getJavaFormatter()));


        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "selectPageStatementId", "selectPage"));
        method1.addParameter(new Parameter(new FullyQualifiedJavaType(shortName), paramName, false));
        topLevelClass.addImportedType(new FullyQualifiedJavaType("com.ifeng.matrix.common.domain.PageResult"));
        method1.setReturnType(new FullyQualifiedJavaType("PageResult<" + shortName + ">"));
        method1.addBodyLine("PageResult pageResult = new PageResult();");
        method1.addBodyLine("pageResult.setCount(" + paramName + "SlaveMapper.countSeletive(" + paramName + "));");
        method1.addBodyLine("pageResult.setResult(" + paramName + "SlaveMapper." + MybatisUtils.getTableProperties(introspectedTable, "selectSelectiveStatementId", "selectSelective") + "(" + paramName + "));");
        method1.addBodyLine("return pageResult;");
        topLevelClass.addMethod(method1);

        answer.add(new GeneratedJavaFile(topLevelClass, serviceProject, context.getJavaFormatter()));

    }

    private void addInsert(List<GeneratedJavaFile> answer, TopLevelClass topLevelClass, Interface serviceInterface, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);
        Method method = new Method();
        method.setName(MybatisUtils.getTableProperties(introspectedTable, "insertStatementId", "insert"));
        method.addParameter(new Parameter(new FullyQualifiedJavaType(shortName), paramName, false));

        method.setReturnType(FullyQualifiedJavaType.getIntInstance());
        serviceInterface.addMethod(method);


        answer.add(new GeneratedJavaFile(serviceInterface, serviceProject, context.getJavaFormatter()));


        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "insertStatementId", "insert"));
        method1.addParameter(new Parameter(new FullyQualifiedJavaType(shortName), paramName, false));
        method1.setReturnType(FullyQualifiedJavaType.getIntInstance());
        //chatUserMasterMapper.insert(chatUser)
        method1.addBodyLine("return " + paramName + "MasterMapper.insert(" + paramName + ");");
        topLevelClass.addMethod(method1);

        answer.add(new GeneratedJavaFile(topLevelClass, serviceProject, context.getJavaFormatter()));
    }

    private void addDeleteByPrimaryKey(List<GeneratedJavaFile> answer, TopLevelClass topLevelClass, Interface serviceInterface, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);
        Method method = new Method();
        method.setName(MybatisUtils.getTableProperties(introspectedTable, "deleteByPrimaryKeyStatementId", "deleteById"));
        if (introspectedTable.getPrimaryKeyColumns().size() > 0)
            method.addParameter(new Parameter(introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType(), "id", false));
        method.setReturnType(FullyQualifiedJavaType.getIntInstance());
        serviceInterface.addMethod(method);

        answer.add(new GeneratedJavaFile(serviceInterface, serviceProject, context.getJavaFormatter()));


        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "deleteByPrimaryKeyStatementId", "deleteById"));
        if (introspectedTable.getPrimaryKeyColumns().size() > 0)
            method1.addParameter(new Parameter(introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType(), "id", false));
        method1.setReturnType(FullyQualifiedJavaType.getIntInstance());
        method1.addBodyLine("return " + paramName + "MasterMapper." + MybatisUtils.getTableProperties(introspectedTable, "deleteByPrimaryKeyStatementId", "deleteById") + "(id);");
        topLevelClass.addMethod(method1);

        answer.add(new GeneratedJavaFile(topLevelClass, serviceProject, context.getJavaFormatter()));
    }

    private void addUpdateByPrimaryKeySelective(List<GeneratedJavaFile> answer, TopLevelClass topLevelClass, Interface serviceInterface, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);
        Method method = new Method();
        method.setName(MybatisUtils.getTableProperties(introspectedTable, "updateByPrimaryKeySelectiveStatementId", "updateSelectiveById"));
        method.addParameter(new Parameter(new FullyQualifiedJavaType(shortName), paramName, false));
        method.setReturnType(FullyQualifiedJavaType.getIntInstance());
        serviceInterface.addMethod(method);

        answer.add(new GeneratedJavaFile(serviceInterface, serviceProject, context.getJavaFormatter()));


        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "updateByPrimaryKeySelectiveStatementId", "updateSelectiveById"));
        method1.addParameter(new Parameter(new FullyQualifiedJavaType(shortName), paramName, false));
        method1.setReturnType(FullyQualifiedJavaType.getIntInstance());
        method1.addBodyLine("return " + paramName + "MasterMapper." + MybatisUtils.getTableProperties(introspectedTable, "updateByPrimaryKeySelectiveStatementId", "updateSelectiveById") + "(" + paramName + ");");
        topLevelClass.addMethod(method1);

        answer.add(new GeneratedJavaFile(topLevelClass, serviceProject, context.getJavaFormatter()));
    }


}
